﻿using RepositoryFramework.Services;
using RepositoryFramework.Validators;
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Portal.Logic.Tests.Units;
using Rhino.Mocks;
using RepositoryFramework;

namespace Portal.Logic.Services.Tests.Units
{
	[TestClass()]
	public abstract class ServiceBaseTests<S, T, V, P, U> : BaseTests
		where S : IServiceBase<T>
		where T : class
		where V : IValidator<T>
		where P : class, IUnitOfWorkProvider<U>
		where U : class, IUnitOfWork
	{
		protected U UnitOfWork { get; set; }

		protected V Validator { get; set; }

		protected P Provider { get; set; }

		protected override void InitializeTest()
		{
			UnitOfWork = Mocks.DynamicMock<U>();
			Provider = Mocks.DynamicMock<P>();
			Expect.Call(Provider.GetReadOnly()).Return(UnitOfWork);
			Expect.Call(Provider.GetTransactional()).Return(UnitOfWork);
		}

		#region IsValid

		[TestMethod()]
		public void IsValid_EntityIsNull_ReturnsFalse()
		{
			Mocks.ReplayAll();

			var service = GetService();
			var result = service.IsValid(null);

			result.Should().BeFalse();
		}

		[TestMethod()]
		public void IsValid_EntityIsValid_ReturnsTrue()
		{
			T entity = Mocks.DynamicMock<T>();
			var validationResult = Mocks.DynamicMock<IValidationResult>();
			SetupResult.For(validationResult.IsValid).Return(true);
			Expect.Call(Validator.Validate(entity)).IgnoreArguments().Return(validationResult);
			Mocks.ReplayAll();

			var service = GetService();
			var result = service.IsValid(entity);

			result.Should().BeTrue();
		}

		[TestMethod()]
		public void IsValid_EntityIsNotValid_ReturnsFalse()
		{
			T entity = Mocks.DynamicMock<T>();
			var validationResult = Mocks.DynamicMock<IValidationResult>();
			SetupResult.For(validationResult.IsValid).Return(false);
			Expect.Call(Validator.Validate(entity)).IgnoreArguments().Return(validationResult);
			Mocks.ReplayAll();

			var service = GetService();
			var result = service.IsValid(entity);

			result.Should().BeFalse();
		}

		#endregion IsValid

		protected abstract S GetService();
	}
}